#include "ZombieSwarm.h"

// Métodos privados ----------------------------------------------------

void
ZombieSwarm::updateSwarmCenter() {

  OpenSteer::Vec3 swarmCenter(0, 0, 0);

  for (_zombiesIt = _zombies.begin();
       _zombiesIt != _zombies.end();
       _zombiesIt++)
    swarmCenter += (*_zombiesIt)->position();

  swarmCenter /= _zombies.size();

  _swarmCenter = swarmCenter;
}

void
ZombieSwarm::updateZombies(const float currentTime,
                           const float elapsedTime) {

  for (_zombiesIt = _zombies.begin();
       _zombiesIt != _zombies.end();
       _zombiesIt++)
    (*_zombiesIt)->update(currentTime, elapsedTime);
}

OpenSteer::Vec3
ZombieSwarm::randomPositionInSwarm() const {

  return _swarmCenter + OpenSteer::randomVectorOnUnitRadiusXZDisk() *
    _maxDistance;
}

// Constructores y destructores ----------------------------------------

ZombieSwarm::ZombieSwarm(btDiscreteDynamicsWorld* pWorld,
                         btCylinderShape* pZombieCollisionShape,
                         Ogre::SceneManager* pSceneManager,
                         OpenSteer::Vec3 position,
                         Human* pHuman,
                         int nZombies) :
  _pWorld(pWorld), _pZombieCollisionShape(pZombieCollisionShape),
  _pSceneManager(pSceneManager), _swarmCenter(position), _pHuman(pHuman),
  _nZombies(nZombies) {

  Zombie* pZombie; // Puntero a zombi

  // Calcular distancia máxima
  updateMaxDistance();

  // Crear nodo para la horda
  _pSwarmNode = _pSceneManager->getRootSceneNode()->createChildSceneNode();

  // Crear zombis
  for (int n = 0; n < nZombies; n++) {

    // pZombieEnt = pSceneManager->createEntity(ZOMBIEMESH);
    // pZombieNode = pSceneManager->createSceneNode();
    // pZombieNode->attachObject(pZombieEnt);
    // _pSwarmNode->addChild(pZombieNode);

    pZombie = new Zombie(_pWorld, _pZombieCollisionShape, _pSceneManager,
                         randomPositionInSwarm(), _pHuman, this);
    _zombies.push_back(pZombie);
  }
}

ZombieSwarm::~ZombieSwarm() { _zombies.clear(); }

void
ZombieSwarm::update(const float currentTime, const float elapsedTime) {

  updateSwarmCenter();
  updateZombies(currentTime, elapsedTime);
}

void
ZombieSwarm::updateMaxDistance() {

  // Distancia máxima es igual a la diagonal del cuadrado que formarian
  // los zombis si los colocaramos formando tal figura
  _maxDistance = (_nZombies / Ogre::Math::Sqrt(_nZombies)) *
    Ogre::Math::Sqrt(2);
}
